/*
 * TweenReader.cpp
 *
 *  Created on: 2009/02/06
 *      Author: Yongshik Cho
 */

#include "TweenReader.h"
#include "../easing/Linear.h"
#include "../easing/Quadratic.h"


const std::string TweenReader::_NAME_TAG			= "name";
const std::string TweenReader::_TIME_TAG			= "time";
const std::string TweenReader::_FRAME_TAG			= "Frame";
const std::string TweenReader::_POSITION_TAG		= "Position";
const std::string TweenReader::_ROTATION_TAG		= "Rotation";
const std::string TweenReader::_ANGLE_TAG			= "angle";
const std::string TweenReader::_SCALE_TAG			= "Scale";
const std::string TweenReader::_LOOPTYPE_TAG		= "LoopType";
const std::string TweenReader::_LOOPCOUNT_TAG		= "LoopCount";
const std::string TweenReader::_LOOPCOUNT_VALUE		= "LOOP_COUNT";
const std::string TweenReader::_ENDLESS_VALUE		= "ENDLESS";
const std::string TweenReader::_EASECLASS_TAG		= "Class";
const std::string TweenReader::_EASEFUNCTION_TAG	= "Function";
const std::string TweenReader::_LINEAR_VALUE		= "Linear";
const std::string TweenReader::_QUADRATIC_VALUE		= "Quadratic";
const std::string TweenReader::_EASEIN_VALUE		= "easeIn";
const std::string TweenReader::_EASEOUT_VALUE		= "easeOut";
const std::string TweenReader::_EASEINOUT_VALUE		= "easeInOut";
const std::string TweenReader::_X_TAG				= "x";
const std::string TweenReader::_Y_TAG				= "y";


void TweenReader::parse(TiXmlElement* element, Renderable* renderable)
{
	if(!element)
		return;

	char* name = (char*)element->Attribute(_NAME_TAG.c_str());
	TiXmlElement* node = element->FirstChildElement(_NAME_TAG.c_str()); if(node) name = (char*)node->GetText();

	if(!name)
		return;

	Tweenable* tweenable = new Tweenable();
	if(!tweenable)
		AltoThrow(Exception::ERR_MEMORY);

	char* loopType = (char*)element->Attribute(_LOOPTYPE_TAG.c_str());
	node = element->FirstChildElement(_LOOPTYPE_TAG.c_str()); if(node) loopType = (char*)node->GetText();
	if(loopType)
	{
		if(_LOOPCOUNT_VALUE == loopType)
			tweenable->setLoopType(Tweenable::LOOP_COUNT);
		else if(_ENDLESS_VALUE == loopType)
			tweenable->setLoopType(Tweenable::ENDLESS);
	}
	else tweenable->setLoopType(Tweenable::LOOP_COUNT);

	int32 loopCount = 0;
	element->Attribute(_LOOPCOUNT_TAG.c_str(), &loopCount);
	node = element->FirstChildElement(_LOOPCOUNT_TAG.c_str()); if(node) loopCount = atoi(node->GetText());

	tweenable->setLoopCount(loopCount);

	parseCallbacks(element, tweenable);

	for(TiXmlElement* frame=element->FirstChildElement(_FRAME_TAG.c_str());frame;frame=frame->NextSiblingElement(_FRAME_TAG.c_str()))
	{
		int32 time, x=0, y=0;
		double sx=1.f, sy=1.f, angle=0.f;

		frame->Attribute(_TIME_TAG.c_str(), &time);
		node = frame->FirstChildElement(_TIME_TAG.c_str()); if(node) time = atoi(node->GetText());

		TiXmlElement* position = frame->FirstChildElement(_POSITION_TAG.c_str());
		if(position)
		{
			position->Attribute(_X_TAG.c_str(), &x);
			node = position->FirstChildElement(_X_TAG.c_str()); if(node) x = atoi(node->GetText());
			position->Attribute(_Y_TAG.c_str(), &y);
			node = position->FirstChildElement(_Y_TAG.c_str()); if(node) y = atoi(node->GetText());
		}

		TiXmlElement* rotation = frame->FirstChildElement(_ROTATION_TAG.c_str());
		if(rotation)
		{
			rotation->Attribute(_ANGLE_TAG.c_str(), &angle);
			node = rotation->FirstChildElement(_ANGLE_TAG.c_str()); if(node) angle = atof(node->GetText());
		}

		TiXmlElement* scale = frame->FirstChildElement(_SCALE_TAG.c_str());
		if(scale)
		{
			scale->Attribute(_X_TAG.c_str(), &sx);
			node = scale->FirstChildElement(_X_TAG.c_str()); if(node) sx = atof(node->GetText());
			scale->Attribute(_Y_TAG.c_str(), &sy);
			node = scale->FirstChildElement(_Y_TAG.c_str()); if(node) sy = atof(node->GetText());
		}

		tweenable->addFrame(
				TweenFrame(time, Vector2D((float)x, (float)y), (float)angle, Vector2D((float)sx, (float)sy), Color::fromRGBA(0.f, 0.f, 0.f, 1.f))
				);
	}

	tweenable->addRenderable(renderable);

#ifdef UNICODE
	{
		TCHAR wstr[512]; memset(wstr, 0, sizeof(wstr));
		::MultiByteToWideChar(CP_UTF8, 0, name, (int32)strlen(name), wstr, 512);
		renderable->setTweenable(wstr, tweenable);
	}
#else
	renderable->setTweenable(name, tweenable);
#endif
}

void TweenReader::parseCallbacks(TiXmlElement* element, Tweenable* tweenable)
{
	if(!element || !tweenable)
		return;

	char* sClass = (char*)element->Attribute(_EASECLASS_TAG.c_str());
	TiXmlElement* node = element->FirstChildElement(_EASECLASS_TAG.c_str()); if(node) sClass = (char*)node->GetText();
	char* sFunction = (char*)element->Attribute(_EASEFUNCTION_TAG.c_str());
	node = element->FirstChildElement(_EASEFUNCTION_TAG.c_str()); if(node) sFunction = (char*)node->GetText();

	if(sClass && sFunction)
	{
		if(_LINEAR_VALUE == sClass)
		{
			if(_EASEIN_VALUE == sFunction)
				tweenable->setCallback(&Linear::easeIn);
			else if(_EASEOUT_VALUE == sFunction)
				tweenable->setCallback(&Linear::easeOut);
			else if(_EASEINOUT_VALUE == sFunction)
				tweenable->setCallback(&Linear::easeInOut);
		}
		if(_QUADRATIC_VALUE == sClass)
		{
			if(_EASEIN_VALUE == sFunction)
				tweenable->setCallback(&Quadratic::easeIn);
			else if(_EASEOUT_VALUE == sFunction)
				tweenable->setCallback(&Quadratic::easeOut);
			else if(_EASEINOUT_VALUE == sFunction)
				tweenable->setCallback(&Quadratic::easeInOut);
		}
	}
}
